﻿namespace UI
{
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Input;

    using Common.ChartDrawing;
    using Common.EventArg;
    using Common.Helpers;
    using Common.Protocol;

    public partial class ChartCanvas
    {
        #region private fields

        private bool isInitialized = false;

        private ChartRenderer renderer;

        private int prevHeight, firstHeight;
        
        private ProtocolInterval interval;
        
        private bool mouseDragging = false;

        #endregion

        public event EventHandler<DateTimeEventArgs> RedLinePositionChanged;

        public event EventHandler<DateTimeEventArgs> CurrentTimeChannged;

        public ChartCanvas(int width)
        {
            this.InitializeComponent();
            this.SnapsToDevicePixels = true;

            this.renderer = new ChartRenderer(this.canvas, width);
            this.renderer.RedLinePositionChanged += this.RendererOnRedLinePositionChanged;
        }

        public List<List<int>> ChannelValues { get; private set; }

        public void Initialize(ProtocolInterval interval)
        {
            this.interval = interval;

            this.firstHeight = (int)this.canvas.RenderSize.Height;

            this.renderer.Initialize(interval);

            this.InvalidateVisual();
            this.isInitialized = true;
        }

        public void ResetChannels()
        {
            this.renderer.ResetChannels();
        }

        #region private functions

        private void CanvasMouseLeftButtonDownHandler(object sender, MouseButtonEventArgs e)
        {
            if (this.interval != null)
            {
                this.renderer.SetRedLinePosition((int)e.GetPosition(sender as Window).Y);
                this.mouseDragging = true;
            }
        }

        private void CanvasMouseLeftButtonUpEventHandler(object sender, MouseButtonEventArgs e)
        {
            this.mouseDragging = false;
        }

        private void CanvasMouseMoveEventHandler(object sender, MouseEventArgs e)
        {
            if (this.mouseDragging)
            {
                this.renderer.SetRedLinePosition((int)e.GetPosition(sender as Window).Y);
            }
        }

        private void RendererOnRedLinePositionChanged(object sender, DateTimeEventArgs dateTime)
        {
            if (this.RedLinePositionChanged != null)
            {
                this.RedLinePositionChanged(this, dateTime);
            }
        }

        private void SizeChangedEventHandler(object sender, SizeChangedEventArgs e)
        {
            if (this.RenderSize.Height != 0)
            {
                if (this.prevHeight != 0)
                {
                    this.renderer.Scale = (float)(this.RenderSize.Height / this.firstHeight);
                }

                this.prevHeight = (int)this.RenderSize.Height;
                this.renderer.ScaleElements();
            }
        }
        
        private void CanvasMouseEnterEventHandler(object sender, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed)
            {
                this.mouseDragging = false;
            }
        }

        private void CanvasMouseDownEventHandler(object sender, MouseButtonEventArgs e)
        {
            this.canvas.Focus();
        }

        private void CanvasMouseWheelEventHandler(object sender, MouseWheelEventArgs e)
        {
            if (this.CurrentTimeChannged != null)
            {
                int shiftMilliseconds = this.interval.StepMilliseconds * (e.Delta / 120);
                DateTime timeToNavigate;
                if (e.Delta >= 0)
                {
                    timeToNavigate = TimeCounter.AddMilliseconds(Constants.CurrentTime, shiftMilliseconds);
                }
                else
                {
                    timeToNavigate = TimeCounter.RemoveMilliseconds(Constants.CurrentTime, -shiftMilliseconds);
                }

                this.CurrentTimeChannged(this, new DateTimeEventArgs(timeToNavigate));
            }
        }

        #endregion
    }
}